package com.xbongbong.paas.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.PaasFormDataEsInitDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsInitVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.service.toolbox.statistic.help.TeamHelp;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.InitDataHelp;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/client")
public class ElasticClientController {
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private InitDataHelp initDataHelp;
    @Resource
    private TeamHelp teamHelp;
    @Resource
    private ThreadPoolTaskExecutor biInitThreadPool;

    private static final Logger LOG = LoggerFactory.getLogger(ElasticClientController.class);
    @RequestMapping(value = "/getClient", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String getClient(@RequestBody @Valid PaasFormDataEsInitDTO paasFormDataEsInitDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsInitDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasPrintSaveVO = new PaasFormDataEsInitVO();
                JSONObject source = JSONObject.parseObject("{\"formId\":16927,\"addTime\":1605169029,\"corpid\":\"zswdcsgs001\",\"data\":{\"text_18\":\"3\",\"text_17\":\"307269\",\"address_1\":{\"address\":\"\",\"province\":\"\",\"city\":\"\",\"district\":\"\"},\"text_19\":null,\"creatorId\":null,\"text_14\":null,\"text_13\":null,\"text_16\":\"xiao001\",\"text_15\":null,\"text_10\":null,\"text_12\":null,\"text_11\":null,\"date_2\":0,\"date_4\":1605169029,\"date_3\":null,\"text_3\":\"2\",\"text_2\":null,\"subForm_2\":null,\"text_5\":\"2\",\"text_4\":\"2\",\"text_7\":\"2\",\"text_6\":\"2\",\"text_9\":null,\"text_8\":\"\",\"text_1\":\"客户测试1006\",\"file_1\":null,\"file_2\":null,\"text_20\":\"客户测试1002\",\"text_22\":null,\"text_66\":null,\"num_1\":5,\"num_2\":null,\"num_3\":0,\"num_4\":2},\"departmentId\":0,\"creatorId\":\"xiao001\",\"del\":0,\"updateTime\":1605169029,\"ownerId\":\"xiao001\",\"serialNo\":\"\",\"my_join_field\":\"saas_customer\",\"dataId\":307316,\"appId\":4451,\"menuId\":18894,\"id\":307316}");
                IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_CUSTOMER;
                source.put(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType());
                for (int i = 1;i<10000;i++){
                    InsertDTO insertDTO = new InsertDTO();
                    insertDTO.setWaitUntil(WriteRequest.RefreshPolicy.NONE);
                    insertDTO.setEsId("zswdcsgs001" + "_" + i);
                    insertDTO.setSource(source);
                    insertDTO.setIndexTypeEnum(indexTypeEnum);
                    List<InsertDTO> insertList = new ArrayList<>();
                    insertList.add(insertDTO);
//                    paasEsModel.insertBatch(insertList,WriteRequest.RefreshPolicy.NONE,false);
                    paasEsModel.insertBatchAsync(insertList,WriteRequest.RefreshPolicy.NONE,false);
                }
                response = new XbbResponse<>(paasPrintSaveVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
    @RequestMapping(value = "/checkNum", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String checkNum(@RequestBody @Valid PaasFormDataEsInitDTO paasFormDataEsInitDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsInitDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasPrintSaveVO = new PaasFormDataEsInitVO();
                for (IndexTypeEnum indexTypeEnum : IndexTypeEnum.getAllEnum()) {
                    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                    sourceBuilder.query(boolQueryBuilder);
                    SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                    searchRequest.source(sourceBuilder);
                    CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
                    countRequest.query(searchRequest.source().query());
                    long count = xbbElasticsearchRestTemplate.count(countRequest);
                    LOG.info(indexTypeEnum.getCode()+"=====ES:====="+count);
                }
                response = new XbbResponse<>(paasPrintSaveVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
    @RequestMapping(value = "/checkDBNum", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String checkDBNum(@RequestBody @Valid PaasFormDataEsInitDTO paasFormDataEsInitDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsInitDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasPrintSaveVO = new PaasFormDataEsInitVO();
                Integer saasMark;
                Integer dbCount = 0;
                for (IndexTypeEnum indexTypeEnum : IndexTypeEnum.getAllEnum()) {
                    //放在内部初始化，防止
                    Map<String, Object> params = new HashMap<>();
                    if ("my_team".equals(indexTypeEnum.getType()) || "product_warehouse".equals(indexTypeEnum.getType()) || "product_stock_info".equals(indexTypeEnum.getType())
                            || "call_center_call_log".equals(indexTypeEnum.getType()) || "contract_performance".equals(indexTypeEnum.getType()) || "my_cc".equals(indexTypeEnum.getType())
                            || "my_evaluation".equals(indexTypeEnum.getType()) || "my_product".equals(indexTypeEnum.getType())
                            || IndexTypeEnum.IDX_PAYMENT_BALANCE.getType().equals(indexTypeEnum.getType())
                            || IndexTypeEnum.IDX_PAY_BALANCE.getType().equals(indexTypeEnum.getType())
                            || IndexTypeEnum.IDX_FUND_ACCOUNT_FLOW.getType().equals(indexTypeEnum.getType())
                    ) {
                        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(indexTypeEnum.getCode());
                        dbCount = teamHelp.getEntitysCount(xbbRefTypeEnum,params);
                    } else if ("404".equals(indexTypeEnum.getType())) {
                        continue;
                    } else if (Objects.equals(ElasticConstant.SUB_FORM_TYPE, indexTypeEnum.getType())) {
                        continue;
                    } else {
                        if(Objects.equals(indexTypeEnum.getCode(),IndexTypeEnum.IDX_FORM_DATA.getCode())){
                            saasMark = SaasMarkEnum.PAAS.getCode();
                        }else {
                            saasMark = SaasMarkEnum.SAAS.getCode();
                        }
                        dbCount = initDataHelp.getEntitysCount(indexTypeEnum.getCode(), saasMark, params);
                    }

                    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                    sourceBuilder.query(boolQueryBuilder);
                    SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                    searchRequest.source(sourceBuilder);
                    CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
                    countRequest.query(searchRequest.source().query());
                    long esCount = xbbElasticsearchRestTemplate.count(countRequest);
                    LOG.info(indexTypeEnum.getIndex() + indexTypeEnum.getType() +"=====ES:====="+esCount+"=====DB:====="+ dbCount);
                }
                response = new XbbResponse<>(paasPrintSaveVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
    @RequestMapping(value = "/removeDBNum", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String removeDBNum(@RequestBody @Valid PaasFormDataEsInitDTO paasFormDataEsInitDTO, BindingResult br) throws Exception {
        XbbResponse<PaasFormDataEsInitVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if(!proBaseConfig.getXbbCode().equals(paasFormDataEsInitDTO.getXbbCode())){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                PaasFormDataEsInitVO paasPrintSaveVO = new PaasFormDataEsInitVO();
                LOG.info("开始处理=====");
                List<Integer> businessTypeList = paasFormDataEsInitDTO.getBusinessTypeList();
                for (Integer businessType : businessTypeList) {
                    IndexTypeEnum indexTypeEnum = null;
                    if(Objects.equals(IndexTypeEnum.IDX_FORM_DATA.getCode(), businessType)){
                        indexTypeEnum = IndexTypeEnum.IDX_FORM_DATA;
                    }else{
                        indexTypeEnum =  EsUtil.getIndexTypeEnum(paasFormDataEsInitDTO.getSaasMark(), businessType);
                        if (Objects.equals(1, paasFormDataEsInitDTO.getSpecial()) && Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                            indexTypeEnum = IndexTypeEnum.IDX_SAAS_CUSTOMER_SPECIAL;
                        }
                    }
                    String tableName = "";
                    XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
                    switch (xbbRefTypeEnum) {
                        case CUSTOMER_MANAGEMENT:
                            tableName = "tb_saas_customer";
                            break;
                        case CONTRACT:
                            tableName = "tb_saas_contract";
                            break;
                        case CONTACT:
                            tableName = "tb_saas_contact";
                            break;
                        case PRODUCT:
                            tableName = "tb_saas_product";
                            break;
                        case SALES_OPPORTUNITY:
                            tableName = "tb_saas_opportunity";
                            break;
                        case INVENTORY:
                            tableName = "tb_saas_inventory";
                            break;
                        case TRANSFER:
                            tableName = "tb_saas_transfer";
                            break;
                        case WAREHOUSE:
                            tableName = "tb_saas_warehouse";
                            break;
                        case COMMUNICATE_PLAN:
                            tableName = "tb_saas_communicate_plan";
                            break;
                        case WORK_REPORT:
                            tableName = "tb_saas_work_report";
                            break;
                        case CUSTOMER_COMMUNICATE:
                            tableName = "tb_saas_customer_communicate";
                            break;
                        case SUPPLIER_COMMUNICATE:
                            tableName = "tb_saas_supplier_communicate";
                            break;
                        case BOM_BILL:
                            tableName = "tb_saas_bom";
                            break;
                        case PRODUCTION_ORDER:
                            tableName = "tb_saas_production_order";
                            break;
                        case PAYMENT:
                            tableName = "tb_saas_payment";
                            break;
                        case PAYMENT_SHEET:
                            tableName = "tb_saas_payment_sheet";
                            break;
                        case PAY_PLAN:
                            tableName = "tb_saas_pay_plan";
                            break;
                        case INVOICE:
                            tableName = "tb_saas_invoice";
                            break;
                        case WORK_ORDER:
                            tableName = "tb_saas_work_order_data";
                            break;
                        case SUPPLIER:
                            tableName = "tb_saas_supplier";
                            break;
                        case SUPPLIER_CONTACT:
                            tableName = "tb_saas_supplier_contact";
                            break;
                        case PURCHASE:
                            tableName = "tb_saas_purchase";
                            break;
                        case RETURNED_PURCHASE:
                            tableName = "tb_saas_returned_purchase";
                            break;
                        case INSTOCK:
                            tableName = "tb_saas_instock";
                            break;
                        case OUTSTOCK:
                            tableName = "tb_saas_outstock";
                            break;
                        case ASSEMBLE:
                            tableName = "tb_saas_assemble";
                            break;
                        case REFUND:
                            tableName = "tb_saas_refund";
                            break;
                        case CONTRACT_PRODUCT:
                            tableName = "tb_saas_contract_product";
                            //TODO
//                                params.put("type", ContractProductTypeEnum.CONTNRACT.getCode());
                            break;
                        case CONTRACT_PERFORMANCE:
                            tableName = "tb_saas_contract_performance";
                            break;
                        default:
                            continue;
                    }
                    boolean flag = true;
                    Long gid = 0L;
                    while (flag){
                        XbbAggregatedPage<PaasFormDataEntity> xbbAggregatedPage = null;
                        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                        BoolQueryBuilder boolQueryBuilder = boolQuery();
                        try {
                            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                            boolQueryBuilder.filter(rangeQuery("id").gt(gid));
                            sourceBuilder.query(boolQueryBuilder);
                            sourceBuilder.size(PaasConstant.ES_MAX_PAGE_SIZE);
                            sourceBuilder.sort("id");
                            sourceBuilder.fetchSource("id", null);
                            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                            searchRequest.source(sourceBuilder);
                            xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(searchRequest, PaasFormDataEntity.class);
                        } catch (Exception e) {
                            LOG.error("",e);
                        }
                        if(xbbAggregatedPage.getTotalElements() != 0){
                            List<PaasFormDataEntity> list = xbbAggregatedPage.getContent();
                            List<Long> arrayList = new ArrayList<>();
                            for (PaasFormDataEntity paasFormDataEntity : list) {
                                arrayList.add(paasFormDataEntity.getId());
                            }
                            gid = list.get(list.size() - 1).getId();
                            LOG.info(indexTypeEnum.getType()+"======"+arrayList);
                            if(StringUtil.isNotEmpty(tableName)){
                                String finalTableName = tableName;
                                Runnable runnable = new Runnable(){
                                    @Override
                                    public void run() {
                                        //初始化数据
                                        try {
                                        } catch (Exception e) {
                                            LOG.error(BiErrorCodeEnum.API_ERROR_241006.getMsg(),e);
                                        }
                                    }
                                };
                                biInitThreadPool.execute(runnable);
                                LOG.info("====dels====="+tableName+"======="+arrayList.size());
                            }
                        }else {
                            flag = false;
                        }
                    }
                }
                LOG.info("结束del=====");
                response = new XbbResponse<>(paasPrintSaveVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

}
